package com.fy.service.server.handler;

import com.alibaba.fastjson.JSONObject;

import com.fy.common.constant.RedisKeyConstant;
import com.fy.common.enums.BooleanEnum;
import com.fy.common.model.im.AttributeChannelModel;
import com.fy.common.model.im.MessageModel;
import com.fy.common.model.im.UserOnlineStatus;
import com.fy.service.server.service.ImService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;

@Component
@ChannelHandler.Sharable
public class SocketServerBusiHandler extends SimpleChannelInboundHandler<Object> {
    public static final AttributeKey<AttributeChannelModel> NETTY_CHANNEL_KEY = AttributeKey.valueOf("netty.channel");

    static final Logger logger = LoggerFactory.getLogger(SocketServerBusiHandler.class);

    //单台服务器所有的channel 连接
    public static ConcurrentHashMap<String, Channel> channelMapping = new ConcurrentHashMap<>();

    @Autowired
    private ImService imService;

    @Autowired
    private RedissonClient redisson;

    /**
     *
     * 连接空闲事件
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt){
        //关闭掉不活跃的channle
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                ctx.close();
            }
        }
    }
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object obj){
        try {
            if(obj instanceof String){
                logger.info("he say : " + obj);
                imService.route(JSONObject.parseObject((String) obj, MessageModel.class), channelHandlerContext);
               // channelHandlerContext.write("收到收到");
            }
        } catch (Exception e) {
            logger.error("channelRead0:", e);
        }
        return;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause){
        logger.error("exceptionCaught Exception",cause);
        //有异常时断掉连接
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx){
        //统一刷新缓存 这样channelRead()中只使用write() 从而提高性能
        ctx.flush();
    }
    // Handler本身被从ChannelPipeline中删除时调用
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx){
      /*  //理论上close执行后会 回调 channelInactive 事件
        ctx.pipeline().remove(this);*/

    }


    //通道添加事件
    @Override
    public void handlerAdded(ChannelHandlerContext ctx){
    }



    //通道活跃事件 连接建立
    @Override
    public void channelActive(ChannelHandlerContext ctx){
        //给每个channel 设置自定义参数
        Attribute<AttributeChannelModel> attr = ctx.channel().attr(NETTY_CHANNEL_KEY);
        AttributeChannelModel newChannel = new AttributeChannelModel();
        attr.setIfAbsent(newChannel);
        logger.info("socket Active:" + attr.get().getChannelKey());
    }
    //通道不活跃事件 连接断开
    @Override
    public void channelInactive(ChannelHandlerContext ctx){
        // channels.remove(ctx.channel());
        Attribute<AttributeChannelModel> attr = ctx.channel().attr(NETTY_CHANNEL_KEY);
        logger.info("socket disconnect:" +attr.get().getChannelKey());
        if (attr.get().getChannelKey() != null) {
            //更新设备最后一次离线时间 和在线状态
            RMapCache<String,JSONObject> mapObj =  redisson.getMapCache(attr.get().getTenantId() + "|" +RedisKeyConstant.NIM_TOKEN_PREFIX + attr.get().getUserId());
            JSONObject jsonObject = mapObj.get(attr.get().getDeviceCode());
            if(jsonObject !=null){
                UserOnlineStatus userOnlineStatus = JSONObject.toJavaObject((JSONObject) jsonObject.get("UserOnlineStatus"),UserOnlineStatus.class) ;


                if(userOnlineStatus != null){
                    userOnlineStatus.setLastOnlineTime(System.currentTimeMillis());
                    userOnlineStatus.setIsOnline(BooleanEnum.FALSE.getValue());
                    jsonObject.put("UserOnlineStatus", JSONObject.toJSON(userOnlineStatus));
                    mapObj.put(attr.get().getDeviceCode(),jsonObject);
                    //移除全局的channle map
                    channelMapping.remove(attr.get().getChannelKey());

                    MessageModel model = new MessageModel();
                    BeanUtils.copyProperties(attr.get(),model);
                    model.setFrom(attr.get().getUserId());
                    imService.groupOfflineInfo(model,userOnlineStatus);
                }
            }


        }
    }
}